﻿using EmailClient.Mail;
using EmailClient.Model;
using EmailClient.ViewModel;
using LumiSoft.Net.IMAP;
using LumiSoft.Net.IMAP.Client;
using LumiSoft.Net.Mail;
using LumiSoft.Net.MIME;
using LumiSoft.Net.SMTP.Client;
using MahApps.Metro.Controls;
using MahApps.Metro.Controls.Dialogs;
using MarkupConverter;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;

namespace EmailClient.View
{
    public partial class LetterView : MetroWindow
    {
        private Letter letter;
        private IMarkupConverter markupConverter;

        public LetterView()
        {
            InitializeComponent();
            markupConverter = new MarkupConverter.MarkupConverter();
            letter.Read = true;
        }

        public LetterView(EmailAccount account)
        {
            InitializeComponent();
            markupConverter = new MarkupConverter.MarkupConverter();
            letter = new Letter();
            letter.AccountId = account.Id;
            letter.Account = account;
            letter.FromSent = account.FullName;
            lvAttachments.ItemsSource = letter.Attachments;
            this.DataContext = letter;
            Body.Text = letter.Account.Signature;
            lvAttachments.Visibility = System.Windows.Visibility.Hidden;

            ManageVisibleControls();
        }

        public LetterView(Letter l)
        {
            InitializeComponent();
            markupConverter = new MarkupConverter.MarkupConverter();
            letter = l;
            this.DataContext = letter;
            if (letter.Attachments == null || letter.Attachments.Count == 0) lvAttachments.Visibility = System.Windows.Visibility.Hidden;
            else
            {
                foreach (var att in letter.Attachments)
                {
                    var it = new System.Windows.Controls.ListViewItem();
                    it.Content = att.Name;
                    it.Tag = att.Id;
                    lvAttachments.Items.Add(it);
                }
            }

            if (!String.IsNullOrEmpty(letter.BodyAsHTML))
            {
                wbBody.NavigateToString(letter.BodyAsHTML);
            }
            else
            {
                var ToHTML = "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">" + markupConverter.ConvertRtfToHtml(letter.BodyAsText);
                wbBody.NavigateToString(ToHTML);
            }

            ManageVisibleControls();
        }

        private void ManageVisibleControls()
        {
            if (lvAttachments.Items.Count > 0) lvAttachments.Visibility = System.Windows.Visibility.Visible;

            if (String.IsNullOrEmpty(letter.MessageId))
            {
                wbBody.Visibility = System.Windows.Visibility.Collapsed;
                Body.Visibility = System.Windows.Visibility.Visible;
                btMoveLetter.Visibility = System.Windows.Visibility.Collapsed;
            }
            else
            {
                wbBody.Visibility = System.Windows.Visibility.Visible;
                Body.Visibility = System.Windows.Visibility.Collapsed;
                btSend.Visibility = System.Windows.Visibility.Collapsed;
                btAddAtt.Visibility = System.Windows.Visibility.Collapsed;
                btMoveLetter.Visibility = System.Windows.Visibility.Visible;

                tbSentTo.IsReadOnly = true;
                tbSubject.IsReadOnly = true;
                tbCC.IsReadOnly = true;
                tbBCC.IsReadOnly = true;
                Body.IsReadOnly = true;

                if (String.IsNullOrEmpty(tbCC.Text)) spCC.Visibility = System.Windows.Visibility.Collapsed;
                if (String.IsNullOrEmpty(tbBCC.Text)) spBCC.Visibility = System.Windows.Visibility.Collapsed;
            }
        }

        private void AddAttachment(object sender, RoutedEventArgs e)
        {
            var openFileDialog = new Microsoft.Win32.OpenFileDialog();
            openFileDialog.Multiselect = true;

            openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            if (openFileDialog.ShowDialog() == true)
            {
                foreach (string fileName in openFileDialog.FileNames)
                {
                    var it = new System.Windows.Controls.ListViewItem();
                    it.Content = Path.GetFileName(fileName) + " (" + ((double)(new FileInfo(fileName).Length / 1000)).ToString("f2") + " kb)";
                    it.Tag = fileName;
                    lvAttachments.Items.Add(it);
                }
                lvAttachments.Visibility = System.Windows.Visibility.Visible;
            }
        }

        private async void SaveItem_Click(object sender, RoutedEventArgs e)
        {
            if (lvAttachments.SelectedItem != null)
            {
                try
                {
                    var x = Convert.ToInt32(((System.Windows.Controls.ListViewItem)lvAttachments.Items[lvAttachments.SelectedIndex]).Tag.ToString());
                    var att = await AttachmentViewModel.Get(letter.Id, x);

                    var dialog = new FolderBrowserDialog();
                    var result = dialog.ShowDialog();
                    if (result == System.Windows.Forms.DialogResult.OK)
                    {
                        var path = dialog.SelectedPath;
                        File.WriteAllBytes(path + "\\" + att.Name.Trim(), att.attach);
                    }
                }
                catch (Exception x)
                {
                    System.Windows.MessageBox.Show("Ошибка: " + x.Message + ".", "Ошибка:", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }

            //if (lvAttachments.Items.Count == 0) lvAttachments.Visibility = System.Windows.Visibility.Hidden;
        }

        private void DelItem_Click(object sender, RoutedEventArgs e)
        {
            if (lvAttachments.SelectedItem != null)
                lvAttachments.Items.Remove(lvAttachments.SelectedItem);

            if (lvAttachments.Items.Count == 0) lvAttachments.Visibility = System.Windows.Visibility.Hidden;

        }

        private async void SentLetter(object sender, RoutedEventArgs e)
        {
            var result = "Письмо отправленно успешно!";
            if (Common.isConnectionAvailable())
            {
                try
                {
                    letter.BodyAsHTML = markupConverter.ConvertRtfToHtml(Body.Text);
                    letter.BodyAsText = Body.Text;
                    Mail_Message message = CreateMessage();

                    if (letter.Account.MailType == "POP3")
                    {
                        if (letter.Account.UseSameUserPassSending) SMTP_Client.QuickSendSmartHost("localhost", letter.Account.outServer, letter.Account.outPort, letter.Account.UseSSL, letter.Account.UserName.Trim(), letter.Account.Password.Trim(), message);
                        else SMTP_Client.QuickSendSmartHost(letter.Account.outServer, letter.Account.outPort, letter.Account.UseSSL, message);

                        letter.MessageId = message.MessageID;
                        letter.FolderId = (await MailFolderViewModel.GetFolder(letter.Account.Id, "Отправленные")).Id;
                        letter.DepartureDate = message.Date;
                        await LetterViewModel.InsertUpdate(letter);

                        if (message.Attachments != null)
                        {
                            var res = await AttachmentViewModel.DeleteAll(letter.Id);
                            if (res == "success")
                            {
                                foreach (var att in message.Attachments)
                                {
                                    var newAtt = new Attachment()
                                    {
                                        Name = att.ContentDisposition.Param_FileName,
                                        ContentTransferEncoding = att.ContentTransferEncoding,
                                        ContentType = att.ContentType.ToString(),
                                        attach = att.DataToByte(),
                                        LetterId = letter.Id
                                    };
                                    await AttachmentViewModel.Insert(newAtt);
                                }
                            }
                        }
                    }
                    else
                    {
                        SMTP_Client.QuickSendSmartHost("localhost", letter.Account.outServer, letter.Account.outPort,
                            letter.Account.UseSSL, letter.Account.UserName.Trim(), letter.Account.Password.Trim(), message);

                        using (var client = IMAP.CreateConnect(letter.Account))
                        {
                            var messageStream = new MemoryStream();
                            message.ToStream(messageStream);
                            messageStream.Position = 0;
                            client.StoreMessage("[Gmail]/Отправленные", IMAP_t_MsgFlags.Parse(IMAP_t_MsgFlags.Draft), DateTime.Now, messageStream, (int)messageStream.Length);
                        }
                    }
                    System.Windows.MessageBox.Show(result, "Информация:", MessageBoxButton.OK, MessageBoxImage.Information);
                }
                catch (Exception x)
                {
                    System.Windows.MessageBox.Show("Ошибка: " + x.Message + ".", "Ошибка:", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            else System.Windows.MessageBox.Show("Ошибка: отсуствует интернет соединение.", "Ошибка:", MessageBoxButton.OK, MessageBoxImage.Error); 

        }

        private async void SaveLetter(object sender, RoutedEventArgs e)
        {
            if (letter.Account.MailType == "POP3" && letter.FolderId == 0)
                letter.FolderId = (await MailFolderViewModel.GetFolder(letter.Account.Id, "Черновики")).Id;
            await LetterViewModel.InsertUpdate(letter);
        }

        private void ForwardLetter(object sender, RoutedEventArgs e)
        {


        }

        private async void MoveLetter(object sender, RoutedEventArgs e)
        {
            ObservableCollection<MailFolder> folders = new ObservableCollection<MailFolder>();
            folders = await MailFolderViewModel.GetFolders(letter.AccountId);
            cbFolders.ItemsSource = folders;
            cbFolders.Visibility = System.Windows.Visibility.Visible;
        }

        private async void cbFolders_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (String.IsNullOrEmpty(letter.MessageId)) return;
            if (cbFolders.SelectedItem != null)
            {
                var selFolder = cbFolders.SelectedItem as MailFolder;
                var typeMail = await AccountViewModel.GetStatus(selFolder.AccountId);
                if (typeMail == "POP3")
                {
                    letter.FolderId = selFolder.Id;
                    await LetterViewModel.InsertUpdate(letter);
                }
                else if (typeMail == "IMAP" && Common.isConnectionAvailable())
                {
                    var curFolder = await MailFolderViewModel.GetFolder(letter.AccountId, letter.FolderId);
                    var oldPath = await IMAP.GetPathFolder(curFolder);
                    var newPath = await IMAP.GetPathFolder(selFolder);

                    try
                    {
                        using (var client = IMAP.CreateConnect(letter.Account))
                        {
                            client.SelectFolder(oldPath);
                            client.MoveMessages(true, IMAP_t_SeqSet.Parse(letter.UID.ToString()), newPath, true);
                            client.CloseFolder();
                        }
                    }
                    catch (Exception x)
                    {
                        System.Windows.MessageBox.Show("Ошибка: " + x.Message + ".", "Ошибка:", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
            }
        }

        private void CloseLetter(object sender, RoutedEventArgs e)
        {
            this.Close();
        }


        /// <summary>
        /// Creates Mime message based on UI data.
        /// </summary>
        private Mail_Message CreateMessage()
        {
            Mail_Message m = new Mail_Message();
            m.MimeVersion = "1.0";
            m.Date = DateTime.Now;
            m.MessageID = MIME_Utils.CreateMessageID();
            m.From = Mail_t_MailboxList.Parse(letter.Account.Email);
            m.To = Mail_t_AddressList.Parse(letter.ToSent);
            m.Subject = letter.Subject;

            if (lvAttachments.Items.Count > 0)
            {
                //--- multipart/mixed -------------------------------------------------------------------------------------------------
                MIME_h_ContentType contentType_multipartMixed = new MIME_h_ContentType(MIME_MediaTypes.Multipart.mixed);
                contentType_multipartMixed.Param_Boundary = Guid.NewGuid().ToString().Replace('-', '.');
                MIME_b_MultipartMixed multipartMixed = new MIME_b_MultipartMixed(contentType_multipartMixed);
                m.Body = multipartMixed;

                //--- multipart/alternative -----------------------------------------------------------------------------------------
                MIME_Entity entity_mulipart_alternative = new MIME_Entity();
                MIME_h_ContentType contentType_multipartAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative);
                contentType_multipartAlternative.Param_Boundary = Guid.NewGuid().ToString().Replace('-', '.');
                MIME_b_MultipartAlternative multipartAlternative = new MIME_b_MultipartAlternative(contentType_multipartAlternative);
                entity_mulipart_alternative.Body = multipartAlternative;
                multipartMixed.BodyParts.Add(entity_mulipart_alternative);

                //--- text/plain ----------------------------------------------------------------------------------------------------
                MIME_Entity entity_text_plain = new MIME_Entity();
                MIME_b_Text text_plain = new MIME_b_Text(MIME_MediaTypes.Text.plain);
                entity_text_plain.Body = text_plain;
                text_plain.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, Body.Text);
                multipartAlternative.BodyParts.Add(entity_text_plain);

                //--- text/html ------------------------------------------------------------------------------------------------------
                MIME_Entity entity_text_html = new MIME_Entity();
                MIME_b_Text text_html = new MIME_b_Text(MIME_MediaTypes.Text.html);
                entity_text_html.Body = text_html;
                text_html.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, letter.BodyAsHTML);
                multipartAlternative.BodyParts.Add(entity_text_html);

                // Create attachment etities: --- applactation/octet-stream -------------------------
                foreach (System.Windows.Controls.ListViewItem item in lvAttachments.Items) multipartMixed.BodyParts.Add(Mail_Message.CreateAttachment(item.Tag.ToString()));
            }
            else
            {
                //--- multipart/alternative -----------------------------------------------------------------------------------------
                MIME_h_ContentType contentType_multipartAlternative = new MIME_h_ContentType(MIME_MediaTypes.Multipart.alternative);
                contentType_multipartAlternative.Param_Boundary = Guid.NewGuid().ToString().Replace('-', '.');
                MIME_b_MultipartAlternative multipartAlternative = new MIME_b_MultipartAlternative(contentType_multipartAlternative);
                m.Body = multipartAlternative;

                //--- text/plain ----------------------------------------------------------------------------------------------------
                MIME_Entity entity_text_plain = new MIME_Entity();
                MIME_b_Text text_plain = new MIME_b_Text(MIME_MediaTypes.Text.plain);
                entity_text_plain.Body = text_plain;
                text_plain.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, Body.Text);
                multipartAlternative.BodyParts.Add(entity_text_plain);

                //--- text/html ------------------------------------------------------------------------------------------------------
                MIME_Entity entity_text_html = new MIME_Entity();
                MIME_b_Text text_html = new MIME_b_Text(MIME_MediaTypes.Text.html);
                entity_text_html.Body = text_html;
                text_html.SetText(MIME_TransferEncodings.QuotedPrintable, Encoding.UTF8, letter.BodyAsHTML);
                multipartAlternative.BodyParts.Add(entity_text_html);
            }

            return m;
        }

        private async void MetroWindow_Closed(object sender, EventArgs e)
        {
            if (!String.IsNullOrEmpty(letter.MessageId) && letter.Account.MailType == "POP3" && letter.Read == false)
            {
                letter.Read = true;
                await LetterViewModel.InsertUpdate(letter);
            }
        }
    }
}
